home *** CD-ROM | disk | FTP | other *** search
/ NetNews Offline 2 / NetNews Offline Volume 2.iso / news / comp / lang / c-part1 / 1897 < prev    next >
Encoding:
Internet Message Format  |  1996-08-05  |  4.9 KB

  1. Path: beach.and.nl!usenet
  2. From: jos@and.nl (Jos A. Horsmeier)
  3. Newsgroups: comp.lang.c
  4. Subject: Re: Newbie question:  Is this code OK?
  5. Date: 17 Jan 1996 16:18:33 GMT
  6. Organization: AND Operations Research B.V.
  7. Message-ID: <4dj7gp$e1o@beach.and.nl>
  8. References: <4di986$fk1@pegasus.interpac.net>
  9. NNTP-Posting-Host: klepzeiker.and.nl
  10. Mime-Version: 1.0
  11. Content-Type: Text/Plain; charset=ISO-8859-1
  12. X-Newsreader: WinVN 0.99.5
  13.  
  14. In article <4di986$fk1@pegasus.interpac.net>, stacys@isis.interpac.net wrote:
  15.  
  16. [ word counting program: ]
  17.  
  18. |I know it's usually not a good idea to increment a loop counter within a 
  19. |loop, but I have 2 nested loops using the same counter.  Was this a bad 
  20. |thing to do?
  21. |
  22. |I have an if statement and a for loop that test for the same things.  Is 
  23. |it possible to somehow combine these into one statement?  I couldn't 
  24. |think of a way to do it.  
  25. |
  26. |Do I need the empty {} after a for loop that has no body?  I assumed if I 
  27. |didn't, the loop would execute the next statement after it.  
  28. |
  29. |int words (char string[80], int length)
  30. |{
  31. |        int i, num_words = 0;
  32. |        
  33. |        for (i=0; i<length; i++)
  34. |        {                               /* if char isn't whitespace */
  35. |                if ((string[i]!='\n') && 
  36. |                        (string[i]!='\t') &&
  37. |                        (string[i]!=' '))
  38. |                {
  39. |                        num_words++;            /* Increment num_words */
  40. |                        for (; i<length, ((string[i]!='\n') &&
  41. |                                (string[i]!='\t') &&   
  42. |                                (string[i]!=' ')); i++) 
  43. |                                 /* and skip past any other */
  44. |                                 /* chars that may be there */
  45. |                        { }     /* loop does all work, nothing in body */
  46. |                }
  47. |        }
  48. |        return (num_words);
  49. |}
  50.  
  51. First let me answer your question about the empty statement in the
  52. second for loop: yes indeed, you do need some sort of a statement 
  53. there (the syntax requires it). The simplest form of an empty statement
  54. is:
  55.  
  56.     for ( <init_part> ; <condition> ; <increment> )
  57.         ; /* a single semi colon */
  58.  
  59. but your '{}' solution works just as fine. About your code -- as far
  60. as I can see everything works fine indeed. Some remarks apply though:
  61.  
  62. You're testing for white space characters. Have a look at the isspace()
  63. function; this function returns a non-zero value if its argument is 
  64. one of: space, tab, carriage return, new-line, form feed and vertical tab.
  65.  
  66. Have a look at the logic behind your program:
  67.  
  68.     as long as we're reading spaces, nothing happens
  69.     else increment a counter and read past all the non-space
  70.     characters until we hit another space character or the end of line.
  71.  
  72. Your program is always in on of the two possible states:
  73.  
  74.     it reads space characters or    (state A)
  75.     it reads non-space characters    (state B)
  76.  
  77. If the program is running in state A and the next character to be read
  78. happens to be a non-space character, the program moves to state B. If
  79. it runs in state B and reads a space character, the program moves back
  80. again to state A. Otherwise, no state transition occurs.
  81.  
  82. If the program moves from state A to state B, it just has read the start
  83. of a new word. Given these observations, we can write another version 
  84. of your program in pseudo code like this:
  85.  
  86.     state=        stateA;
  87.     num_words= 0;
  88.  
  89.     while more characters to read {
  90.  
  91.         c= current character;
  92.  
  93.         if (isspace(c)) {
  94.             if (state == stateB)
  95.                 state= stateA;
  96.         }
  97.         else
  98.             if (state == stateA) {
  99.                 num_words++;
  100.                 state= stateB;
  101.             }
  102.     }
  103.  
  104. Have a look at the if-then-else part -- we can 'optimize' the state
  105. transitions a bit:
  106.  
  107.         if (isspace(c)) {
  108.             state= stateA;
  109.         else if (state == stateA) {
  110.             num_words++;
  111.             state= stateB;
  112.         }
  113.  
  114. Let's turn this pseudo cody thingy into a C function; we represent stateA
  115. by an int 1 (or any other non-zero value) and stateB by an int 0. While
  116. we're at it, in C a string is usually represented by a zero terminated
  117. array of characters; lets stick to this parlance:
  118.  
  119.     int    words(char* string) {
  120.  
  121.     int    state= 0;
  122.     int    num_words= 0;
  123.  
  124.         for (; *string; string++)
  125.  
  126.             if (isspace(*string))
  127.                 state= 1;
  128.             else if (state) {
  129.                 num_words++;
  130.                 state= 0;
  131.             }
  132.  
  133.         return num_words;
  134.     }
  135.  
  136. As you can see this revised function does the same amount of work as
  137. your version, i.e. it reads every character once until everything is
  138. read, but the 'functionality' of it all is not scattered around different
  139. for loops and if statements.
  140.  
  141. If we really carry things over the edge, we could've implemented the
  142. if-then-else part as:
  143.  
  144.     if (isspace(*string)^state) {
  145.         num_words+= state;
  146.         state= !state;
  147.     }
  148.  
  149. but I wouldn't encourage such type of programming (leave that to idiots
  150. who don't know any better, like me ;-)        
  151.  
  152. I don't want to criticize your code at all, after all you're just starting
  153. and you're doing a fine job, but you've asked for comments, so here you 
  154. got them ;-)
  155.  
  156. kind regards,
  157.  
  158. Jos aka jos@and.nl
  159. -- 
  160. Atnwgqkrl gy zit vgksr, ug qshiqwtzoeqs!
  161.  
  162.